﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace Framework.Event
{
    public sealed class InlineDomainEventHandler : IDomainEventHandler
    {
        #region Private Fields
        private readonly Type domainEventType;
        private readonly Func<IDomainEvent, object> action;
        #endregion

        #region Ctor
        /// <summary>
        /// Initializes a new instance of <c>InlineDomainEventHandler</c> class.
        /// </summary>
        /// <param name="aggregateRoot">The instance of the aggregate root within which the domain event
        /// was raised and handled.</param>
        /// <param name="mi">The method which handles the domain event.</param>
        public InlineDomainEventHandler(IEntity entity, MethodInfo mi)
        {
            ParameterInfo[] parameters = mi.GetParameters();
            if (parameters == null || parameters.Count() == 0)
            {
                throw new ArgumentException(string.Format("EX_INVALID_HANDLER_SIGNATURE {0}", mi.Name), "mi");
            }
            domainEventType = parameters[0].ParameterType;
            action = domainEvent =>
            {
                return mi.Invoke(entity, new object[] { domainEvent });
            };
        }
        #endregion

        #region IDomainEventHandler Members
        /// <summary>
        /// Handles the specified domain event.
        /// </summary>
        /// <param name="message">The domain event to be handled.</param>
        public object Handle(IDomainEvent message)
        {
            return action(message);
        }
        /// <summary>
        /// Checks whether the specified domain event could be handled by the current handler.
        /// </summary>
        /// <param name="domainEvent">The domain event to be checked.</param>
        /// <returns>True if the specified domain event can be handled by the current handler, otherwise false.</returns>
        public bool CanHandle(IDomainEvent domainEvent)
        {
            return domainEventType.Equals(domainEvent.GetType());
        }

        #endregion
    }
}
